From e7b290debbca685220a0c96ddc8c5aab13138f4f Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 24 Oct 2020 13:13:07 -0400 Subject: [PATCH] a11y: Improve child notification for toplevels We need to translate the list model position into an accessible tree position, since hidden toplevels will be skipped. While we are at it, add an api for this notification that will be used in the next commit. --- gtk/a11y/gtkatspiroot.c | 78 +++++++++++++++++++++++++--------- gtk/a11y/gtkatspirootprivate.h | 6 +++ 2 files changed, 65 insertions(+), 19 deletions(-) diff --git a/gtk/a11y/gtkatspiroot.c b/gtk/a11y/gtkatspiroot.c index 8c35fb6a29..21beb2eab3 100644 --- a/gtk/a11y/gtkatspiroot.c +++ b/gtk/a11y/gtkatspiroot.c @@ -412,8 +412,59 @@ root_toplevels__items_changed (GtkAtSpiRoot *self, guint added, GListModel *toplevels) { - GtkWidget *window = g_list_model_get_item (self->toplevels, position); - GVariant *window_ref = NULL; + if (added == 1 && removed == 0) + { + GtkWidget *window; + + window = GTK_WIDGET (g_list_model_get_item (self->toplevels, position)); + gtk_at_spi_root_child_changed (self, + GTK_ACCESSIBLE_CHILD_STATE_ADDED, + G_MAXUINT, + window); + g_object_unref (window); + } + else if (added == 0 && removed == 1) + { + gtk_at_spi_root_child_changed (self, + GTK_ACCESSIBLE_CHILD_STATE_REMOVED, + position, + NULL); + } + else + { + g_assert_not_reached (); + } +} + +void +gtk_at_spi_root_child_changed (GtkAtSpiRoot *self, + GtkAccessibleChildState state, + guint position, + GtkWidget *window) +{ + guint n, i; + int idx = 0; + GVariant *window_ref; + + /* We can be called either with a valid position and window == NULL + * or with position == G_MAXUINT and a valid window. In both cases, + * we need to determine the index of where the removed object would + * have been in the accessible tree. + */ + for (i = 0, n = g_list_model_get_n_items (self->toplevels); i < n; i++) + { + GtkAccessible *item = g_list_model_get_item (self->toplevels, i); + + g_object_unref (item); + + if (i == position || item == GTK_ACCESSIBLE (window)) + break; + + if (!gtk_accessible_should_present (item)) + continue; + + idx++; + } if (window == NULL) { @@ -426,23 +477,12 @@ root_toplevels__items_changed (GtkAtSpiRoot *self, window_ref = gtk_at_spi_context_to_ref (GTK_AT_SPI_CONTEXT (context)); } - if (added == 1 && removed == 0) - gtk_at_spi_emit_children_changed (self->connection, - self->root_path, - GTK_ACCESSIBLE_CHILD_STATE_ADDED, - position, - gtk_at_spi_root_to_ref (self), - window_ref); - else if (removed == 1 && added == 0) - gtk_at_spi_emit_children_changed (self->connection, - self->root_path, - GTK_ACCESSIBLE_CHILD_STATE_REMOVED, - position, - gtk_at_spi_root_to_ref (self), - window_ref); - - if (window != NULL) - g_object_unref (window); + gtk_at_spi_emit_children_changed (self->connection, + self->root_path, + state, + idx, + gtk_at_spi_root_to_ref (self), + window_ref); } static void diff --git a/gtk/a11y/gtkatspirootprivate.h b/gtk/a11y/gtkatspirootprivate.h index 0ce5e6b693..12cba41085 100644 --- a/gtk/a11y/gtkatspirootprivate.h +++ b/gtk/a11y/gtkatspirootprivate.h @@ -42,4 +42,10 @@ gtk_at_spi_root_get_cache (GtkAtSpiRoot *self); GVariant * gtk_at_spi_root_to_ref (GtkAtSpiRoot *self); +void +gtk_at_spi_root_child_changed (GtkAtSpiRoot *self, + GtkAccessibleChildState state, + guint position, + GtkWidget *window); + G_END_DECLS -- 2.30.2